package com.ncsc.lmis.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.ncsc.lmis.model.SaleLoanContract;
import com.ncsc.lmis.model.HrEmp;
import com.ncsc.lmis.model.SaleConditionType;
import com.ncsc.lmis.model.SaleLoanContractCcRate;
import com.ncsc.lmis.model.SaleLoanContractConfiscate;
import com.ncsc.lmis.model.SaleLoanContractDebtMoratorium;
import com.ncsc.lmis.model.SaleLoanContractDiscretion;
import com.ncsc.lmis.model.SaleLoanContractGuarantor;
import com.ncsc.lmis.model.SaleLoanContractLog;
import com.ncsc.lmis.model.SaleLoanContractReInfo;
import com.ncsc.lmis.model.SaleLoanContractReceiptCancel;
import com.ncsc.lmis.model.SaleLoanContractRefdoc01;
import com.ncsc.lmis.model.SaleLoanContractRefdoc02;
import com.ncsc.lmis.model.SaleLoanContractRefdoc03;
import com.ncsc.lmis.model.SaleLoanContractRefdocInvoice;
import com.ncsc.lmis.model.SaleLoanGrade;
import com.ncsc.lmis.model.SaleLoanPayment;
import com.ncsc.lmis.model.SaleLoanPaymentTemplate;
import com.ncsc.lmis.model.SysAddressProvince;
import com.ncsc.lmis.model.SysApproveLevel;
import com.ncsc.lmis.model.SysCust;
import com.ncsc.lmis.model.SysIncomeLevel;
import com.ncsc.lmis.model.SysNameTitle;
import com.ncsc.lmis.model.SysOrg;
import com.ncsc.lmis.model.SysVehicleBrand;
import java.util.Iterator;

/**
 * Backing bean for SaleLoanContract entities.
 * <p>
 * This class provides CRUD functionality for all SaleLoanContract entities. It focuses
 * purely on Java EE 6 standards (e.g. <tt>&#64;ConversationScoped</tt> for
 * state management, <tt>PersistenceContext</tt> for persistence,
 * <tt>CriteriaBuilder</tt> for searches) rather than introducing a CRUD framework or
 * custom base class.
 */

@Named
@Stateful
@ConversationScoped
public class SaleLoanContractBean implements Serializable
{

   private static final long serialVersionUID = 1L;

   /*
    * Support creating and retrieving SaleLoanContract entities
    */

   private Long id;

   public Long getId()
   {
      return this.id;
   }

   public void setId(Long id)
   {
      this.id = id;
   }

   private SaleLoanContract saleLoanContract;

   public SaleLoanContract getSaleLoanContract()
   {
      return this.saleLoanContract;
   }

   @Inject
   private Conversation conversation;

   @PersistenceContext(type = PersistenceContextType.EXTENDED)
   private EntityManager entityManager;

   public String create()
   {

      this.conversation.begin();
      return "create?faces-redirect=true";
   }

   public void retrieve()
   {

      if (FacesContext.getCurrentInstance().isPostback())
      {
         return;
      }

      if (this.conversation.isTransient())
      {
         this.conversation.begin();
      }

      if (this.id == null)
      {
         this.saleLoanContract = this.example;
      }
      else
      {
         this.saleLoanContract = findById(getId());
      }
   }

   public SaleLoanContract findById(Long id)
   {

      return this.entityManager.find(SaleLoanContract.class, id);
   }

   /*
    * Support updating and deleting SaleLoanContract entities
    */

   public String update()
   {
      this.conversation.end();

      try
      {
         if (this.id == null)
         {
            this.entityManager.persist(this.saleLoanContract);
            return "search?faces-redirect=true";
         }
         else
         {
            this.entityManager.merge(this.saleLoanContract);
            return "view?faces-redirect=true&id=" + this.saleLoanContract.getRecNo();
         }
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   public String delete()
   {
      this.conversation.end();

      try
      {
         SaleLoanContract deletableEntity = findById(getId());
         HrEmp hrEmp = deletableEntity.getHrEmp();
         hrEmp.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setHrEmp(null);
         this.entityManager.merge(hrEmp);
         SysCust sysCust = deletableEntity.getSysCust();
         sysCust.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysCust(null);
         this.entityManager.merge(sysCust);
         SysVehicleBrand sysVehicleBrand = deletableEntity.getSysVehicleBrand();
         sysVehicleBrand.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysVehicleBrand(null);
         this.entityManager.merge(sysVehicleBrand);
         SaleLoanGrade saleLoanGrade = deletableEntity.getSaleLoanGrade();
         saleLoanGrade.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSaleLoanGrade(null);
         this.entityManager.merge(saleLoanGrade);
         SysOrg sysOrg = deletableEntity.getSysOrg();
         sysOrg.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysOrg(null);
         this.entityManager.merge(sysOrg);
         SysIncomeLevel sysIncomeLevel = deletableEntity.getSysIncomeLevel();
         sysIncomeLevel.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysIncomeLevel(null);
         this.entityManager.merge(sysIncomeLevel);
         SysNameTitle sysNameTitle = deletableEntity.getSysNameTitle();
         sysNameTitle.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysNameTitle(null);
         this.entityManager.merge(sysNameTitle);
         SysApproveLevel sysApproveLevel = deletableEntity.getSysApproveLevel();
         sysApproveLevel.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysApproveLevel(null);
         this.entityManager.merge(sysApproveLevel);
         SaleConditionType saleConditionType = deletableEntity.getSaleConditionType();
         saleConditionType.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSaleConditionType(null);
         this.entityManager.merge(saleConditionType);
         SysAddressProvince sysAddressProvince = deletableEntity.getSysAddressProvince();
         sysAddressProvince.getSaleLoanContracts().remove(deletableEntity);
         deletableEntity.setSysAddressProvince(null);
         this.entityManager.merge(sysAddressProvince);
         Iterator<SaleLoanContractDebtMoratorium> iterSaleLoanContractDebtMoratoriums = deletableEntity.getSaleLoanContractDebtMoratoriums().iterator();
         for (; iterSaleLoanContractDebtMoratoriums.hasNext();)
         {
            SaleLoanContractDebtMoratorium nextInSaleLoanContractDebtMoratoriums = iterSaleLoanContractDebtMoratoriums.next();
            nextInSaleLoanContractDebtMoratoriums.setSaleLoanContract(null);
            iterSaleLoanContractDebtMoratoriums.remove();
            this.entityManager.merge(nextInSaleLoanContractDebtMoratoriums);
         }
         Iterator<SaleLoanContractReceiptCancel> iterSaleLoanContractReceiptCancels = deletableEntity.getSaleLoanContractReceiptCancels().iterator();
         for (; iterSaleLoanContractReceiptCancels.hasNext();)
         {
            SaleLoanContractReceiptCancel nextInSaleLoanContractReceiptCancels = iterSaleLoanContractReceiptCancels.next();
            nextInSaleLoanContractReceiptCancels.setSaleLoanContract(null);
            iterSaleLoanContractReceiptCancels.remove();
            this.entityManager.merge(nextInSaleLoanContractReceiptCancels);
         }
         Iterator<SaleLoanPayment> iterSaleLoanPayments = deletableEntity.getSaleLoanPayments().iterator();
         for (; iterSaleLoanPayments.hasNext();)
         {
            SaleLoanPayment nextInSaleLoanPayments = iterSaleLoanPayments.next();
            nextInSaleLoanPayments.setSaleLoanContract(null);
            iterSaleLoanPayments.remove();
            this.entityManager.merge(nextInSaleLoanPayments);
         }
         Iterator<SaleLoanContractRefdoc01> iterSaleLoanContractRefdoc01s = deletableEntity.getSaleLoanContractRefdoc01s().iterator();
         for (; iterSaleLoanContractRefdoc01s.hasNext();)
         {
            SaleLoanContractRefdoc01 nextInSaleLoanContractRefdoc01s = iterSaleLoanContractRefdoc01s.next();
            nextInSaleLoanContractRefdoc01s.setSaleLoanContract(null);
            iterSaleLoanContractRefdoc01s.remove();
            this.entityManager.merge(nextInSaleLoanContractRefdoc01s);
         }
         SaleLoanContractReInfo saleLoanContractReInfo = deletableEntity.getSaleLoanContractReInfo();
         saleLoanContractReInfo.setSaleLoanContract(null);
         this.entityManager.merge(saleLoanContractReInfo);
         Iterator<SaleLoanContractGuarantor> iterSaleLoanContractGuarantors = deletableEntity.getSaleLoanContractGuarantors().iterator();
         for (; iterSaleLoanContractGuarantors.hasNext();)
         {
            SaleLoanContractGuarantor nextInSaleLoanContractGuarantors = iterSaleLoanContractGuarantors.next();
            nextInSaleLoanContractGuarantors.setSaleLoanContract(null);
            iterSaleLoanContractGuarantors.remove();
            this.entityManager.merge(nextInSaleLoanContractGuarantors);
         }
         Iterator<SaleLoanContractLog> iterSaleLoanContractLogs = deletableEntity.getSaleLoanContractLogs().iterator();
         for (; iterSaleLoanContractLogs.hasNext();)
         {
            SaleLoanContractLog nextInSaleLoanContractLogs = iterSaleLoanContractLogs.next();
            nextInSaleLoanContractLogs.setSaleLoanContract(null);
            iterSaleLoanContractLogs.remove();
            this.entityManager.merge(nextInSaleLoanContractLogs);
         }
         Iterator<SaleLoanContractCcRate> iterSaleLoanContractCcRates = deletableEntity.getSaleLoanContractCcRates().iterator();
         for (; iterSaleLoanContractCcRates.hasNext();)
         {
            SaleLoanContractCcRate nextInSaleLoanContractCcRates = iterSaleLoanContractCcRates.next();
            nextInSaleLoanContractCcRates.setSaleLoanContract(null);
            iterSaleLoanContractCcRates.remove();
            this.entityManager.merge(nextInSaleLoanContractCcRates);
         }
         Iterator<SaleLoanContractRefdocInvoice> iterSaleLoanContractRefdocInvoices = deletableEntity.getSaleLoanContractRefdocInvoices().iterator();
         for (; iterSaleLoanContractRefdocInvoices.hasNext();)
         {
            SaleLoanContractRefdocInvoice nextInSaleLoanContractRefdocInvoices = iterSaleLoanContractRefdocInvoices.next();
            nextInSaleLoanContractRefdocInvoices.setSaleLoanContract(null);
            iterSaleLoanContractRefdocInvoices.remove();
            this.entityManager.merge(nextInSaleLoanContractRefdocInvoices);
         }
         Iterator<SaleLoanContractDiscretion> iterSaleLoanContractDiscretions = deletableEntity.getSaleLoanContractDiscretions().iterator();
         for (; iterSaleLoanContractDiscretions.hasNext();)
         {
            SaleLoanContractDiscretion nextInSaleLoanContractDiscretions = iterSaleLoanContractDiscretions.next();
            nextInSaleLoanContractDiscretions.setSaleLoanContract(null);
            iterSaleLoanContractDiscretions.remove();
            this.entityManager.merge(nextInSaleLoanContractDiscretions);
         }
         Iterator<SaleLoanPaymentTemplate> iterSaleLoanPaymentTemplates = deletableEntity.getSaleLoanPaymentTemplates().iterator();
         for (; iterSaleLoanPaymentTemplates.hasNext();)
         {
            SaleLoanPaymentTemplate nextInSaleLoanPaymentTemplates = iterSaleLoanPaymentTemplates.next();
            nextInSaleLoanPaymentTemplates.setSaleLoanContract(null);
            iterSaleLoanPaymentTemplates.remove();
            this.entityManager.merge(nextInSaleLoanPaymentTemplates);
         }
         Iterator<SaleLoanContractConfiscate> iterSaleLoanContractConfiscates = deletableEntity.getSaleLoanContractConfiscates().iterator();
         for (; iterSaleLoanContractConfiscates.hasNext();)
         {
            SaleLoanContractConfiscate nextInSaleLoanContractConfiscates = iterSaleLoanContractConfiscates.next();
            nextInSaleLoanContractConfiscates.setSaleLoanContract(null);
            iterSaleLoanContractConfiscates.remove();
            this.entityManager.merge(nextInSaleLoanContractConfiscates);
         }
         Iterator<SaleLoanContractRefdoc02> iterSaleLoanContractRefdoc02s = deletableEntity.getSaleLoanContractRefdoc02s().iterator();
         for (; iterSaleLoanContractRefdoc02s.hasNext();)
         {
            SaleLoanContractRefdoc02 nextInSaleLoanContractRefdoc02s = iterSaleLoanContractRefdoc02s.next();
            nextInSaleLoanContractRefdoc02s.setSaleLoanContract(null);
            iterSaleLoanContractRefdoc02s.remove();
            this.entityManager.merge(nextInSaleLoanContractRefdoc02s);
         }
         Iterator<SaleLoanContractRefdoc03> iterSaleLoanContractRefdoc03s = deletableEntity.getSaleLoanContractRefdoc03s().iterator();
         for (; iterSaleLoanContractRefdoc03s.hasNext();)
         {
            SaleLoanContractRefdoc03 nextInSaleLoanContractRefdoc03s = iterSaleLoanContractRefdoc03s.next();
            nextInSaleLoanContractRefdoc03s.setSaleLoanContract(null);
            iterSaleLoanContractRefdoc03s.remove();
            this.entityManager.merge(nextInSaleLoanContractRefdoc03s);
         }
         this.entityManager.remove(deletableEntity);
         this.entityManager.flush();
         return "search?faces-redirect=true";
      }
      catch (Exception e)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
         return null;
      }
   }

   /*
    * Support searching SaleLoanContract entities with pagination
    */

   private int page;
   private long count;
   private List<SaleLoanContract> pageItems;

   private SaleLoanContract example = new SaleLoanContract();

   public int getPage()
   {
      return this.page;
   }

   public void setPage(int page)
   {
      this.page = page;
   }

   public int getPageSize()
   {
      return 10;
   }

   public SaleLoanContract getExample()
   {
      return this.example;
   }

   public void setExample(SaleLoanContract example)
   {
      this.example = example;
   }

   public void search()
   {
      this.page = 0;
   }

   public void paginate()
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

      // Populate this.count

      CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
      Root<SaleLoanContract> root = countCriteria.from(SaleLoanContract.class);
      countCriteria = countCriteria.select(builder.count(root)).where(
            getSearchPredicates(root));
      this.count = this.entityManager.createQuery(countCriteria)
            .getSingleResult();

      // Populate this.pageItems

      CriteriaQuery<SaleLoanContract> criteria = builder.createQuery(SaleLoanContract.class);
      root = criteria.from(SaleLoanContract.class);
      TypedQuery<SaleLoanContract> query = this.entityManager.createQuery(criteria
            .select(root).where(getSearchPredicates(root)));
      query.setFirstResult(this.page * getPageSize()).setMaxResults(
            getPageSize());
      this.pageItems = query.getResultList();
   }

   private Predicate[] getSearchPredicates(Root<SaleLoanContract> root)
   {

      CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
      List<Predicate> predicatesList = new ArrayList<Predicate>();

      HrEmp hrEmp = this.example.getHrEmp();
      if (hrEmp != null)
      {
         predicatesList.add(builder.equal(root.get("hrEmp"), hrEmp));
      }
      SysCust sysCust = this.example.getSysCust();
      if (sysCust != null)
      {
         predicatesList.add(builder.equal(root.get("sysCust"), sysCust));
      }
      SysVehicleBrand sysVehicleBrand = this.example.getSysVehicleBrand();
      if (sysVehicleBrand != null)
      {
         predicatesList.add(builder.equal(root.get("sysVehicleBrand"), sysVehicleBrand));
      }
      SaleLoanGrade saleLoanGrade = this.example.getSaleLoanGrade();
      if (saleLoanGrade != null)
      {
         predicatesList.add(builder.equal(root.get("saleLoanGrade"), saleLoanGrade));
      }
      SysOrg sysOrg = this.example.getSysOrg();
      if (sysOrg != null)
      {
         predicatesList.add(builder.equal(root.get("sysOrg"), sysOrg));
      }

      return predicatesList.toArray(new Predicate[predicatesList.size()]);
   }

   public List<SaleLoanContract> getPageItems()
   {
      return this.pageItems;
   }

   public long getCount()
   {
      return this.count;
   }

   /*
    * Support listing and POSTing back SaleLoanContract entities (e.g. from inside an
    * HtmlSelectOneMenu)
    */

   public List<SaleLoanContract> getAll()
   {

      CriteriaQuery<SaleLoanContract> criteria = this.entityManager
            .getCriteriaBuilder().createQuery(SaleLoanContract.class);
      return this.entityManager.createQuery(
            criteria.select(criteria.from(SaleLoanContract.class))).getResultList();
   }

   @Resource
   private SessionContext sessionContext;

   public Converter getConverter()
   {

      final SaleLoanContractBean ejbProxy = this.sessionContext.getBusinessObject(SaleLoanContractBean.class);

      return new Converter()
      {

         @Override
         public Object getAsObject(FacesContext context,
               UIComponent component, String value)
         {

            return ejbProxy.findById(Long.valueOf(value));
         }

         @Override
         public String getAsString(FacesContext context,
               UIComponent component, Object value)
         {

            if (value == null)
            {
               return "";
            }

            return String.valueOf(((SaleLoanContract) value).getRecNo());
         }
      };
   }

   /*
    * Support adding children to bidirectional, one-to-many tables
    */

   private SaleLoanContract add = new SaleLoanContract();

   public SaleLoanContract getAdd()
   {
      return this.add;
   }

   public SaleLoanContract getAdded()
   {
      SaleLoanContract added = this.add;
      this.add = new SaleLoanContract();
      return added;
   }
}